<?php
Cinnamon::loadClass('ISession');

/**
 * Default Cinnamon Session
 *
 * Session class that is used during the regular and ajax modes
 */
class Session implements ISession {
	
	/**
	 * Default constructor
	 */	 
	public function __construct() {
	 	session_name('CSESID');
		session_start();
		
		// load filters values from cookies	(if that's necessary)	
		foreach ( (array) $_COOKIE as $name=>$value ) {
				// Just set all the available cookie variables
				$this->set($name, $value);
		}		
		
		// load filters values from database (if that's necessary)
		$options = Cinnamon::registry('config')->getAll('filters.history.*');
		foreach ( (array) $options as $name=>$value ) {
			$name = str_replace('filters.history', 'filters', $name);		// convert option variable name to session variable name
			if ( !$this->exists($name) ) {		// if the variable exists, dont overwrite it!
				$this->set($name, $value);
			}
		}
	} 
	
	/**
	 * Returns the (unique) identifier for this session
	 */
	public function getIdentifier() {
		return ( session_id() );
	}	
	 
	 
	/**
	 * Updates the value of the specified variable name for this session.
	 *
	 * @param string name the variable name to be updated (use the dots for hierarchy - avoid '_')
	 * @param string value the new value
	 */
	public function set($name, $value) {
		if ( preg_match('/^filters\./', $name) ) {	// we have to update the configuration as well
			$config = Cinnamon::registry('config');
			$cfgname = str_replace('filters', 'filters.history', $name);	// convert session variable name to option variable name
			if ( !$config->exists($cfgname) ) {
				$config->add($cfgname, $value, true);
			} else {
				$config->set($cfgname, $value);
			}
		}
		
		$name = strtoupper($name);
		$_SESSION[$name] = $this->maybeSerialize($value);	
	}
	
	/**
	 * Returns the value of the value with the specified name
	 *
	 * @pamra string name the variable name
	 */
	public function get($name) {
		$name = strtoupper($name);
		return ( $this->maybeUnserialize($_SESSION[$name]) );
	}
	
	/**
	 * Returns true only and only if the specified variable exists
	 */
	public function exists($name) {
		$name = strtoupper($name);
		return ( isset($_SESSION[$name]) );
	}
	
	/**
	 * Returns true only and only if the specified login and password are correct. If they are correct, authenticates the user for this session. See isAuthenticated for more details.
	 *
	 * @param string login the login (user name) to be checked
	 * @param string password the password (not encoded) to be checked
	 * @return true only and only if the specified login and password are correct
	 */
	public function login($login, $password) {
		$config = Cinnamon::registry('config');
		
		$password = md5($password);
		if ( strcmp($login, $config->get('auth.login')) == 0 && strcmp($password, $config->get('auth.pass')) == 0 ) {
			// store authentication details
			$this->set('auth.login', $login);
			$this->set('auth.pass', $password);
			return true;
		}
		
		// login failed
		return false;	
	}
	
	/**
	 * Deletes the authentication details for this session
	 */
	public function logout() {
		session_destroy();	// TODO: is that the right method? or should I unset the auth.* variables?
		header('Location: '. CSEURL .'/index.php');		
	}
	
	/**
	 * Returns true only and only if this user is authenticated
	 */
	public function isAuthenticated() {
		$config = Cinnamon::registry('config');
		return ( strcmp($config->get('auth.login'), $this->get('auth.login')) == 0 && strcmp($config->get('auth.pass'), $this->get('auth.pass')) == 0 );
	}
	
	/**
	 * Applies the authorization policy. If the user does not have the required permissions, it will be redirected to the login screen.
	 *
	 * @param bool strict authentication is in strict mode. That means that the option 'auth.required' is ignored. This is an optional parameter. The default value is false.	 
	 */
	public function applyAuthenticationPolicy($strict=false) {
		$authenticated = $this->isAuthenticated();
		$public = ( strcmp(Cinnamon::registry('config')->get('auth.required'), 'n') == 0 );
		if ( !$authenticated && ( $strict || !$public ) ) {
			header('Location: '. CSEURL .'/cse-login.php?url='. urlencode($_SERVER['REQUEST_URI']));
			die();
		}
	}
	
	/**
	 * Common Serialization functions
	 */
	protected function maybeUnserialize($item) {
		if ( false !== $gm = @ unserialize($item) ) {
			return $gm;
		}
		return $item;
	}
	protected function maybeSerialize($item) {
		if ( is_object($item) || is_array($item) ) {
			return serialize($item);
		}
		return $item;
	}		
}

?>